function [ GDOP, PDOP, HDOP, VDOP, TDOP, H ] = dops( RUser, RSat, accoutForClkErr ) %#codegen
%DOPS 计算精度因子
%
% Input Arguments:
% RUser: 长度为n（n=2或3，2表示二维情形，3表示三维情形）的列向量，用户坐标
% RSat: m*n矩阵，m为卫星数，卫星坐标
% accoutForClkErr: 逻辑标量，true表示考虑时钟误差，默认为true
%
% Output Arguments:
% GDOP, PDOP, HDOP, VDOP, TDOP: 标量，精度因子，二维情形下除GDOP、HDOP外均为NaN，不考虑时钟误差时TDOP为NaN
% H: m*n矩阵（当不考虑时钟误差时）或m*(n+1)矩阵（当考虑时钟误差时），最小二乘平差求解系数矩阵
%
% References:
% [1] Mohinder S. Grewal. GPS惯性导航组合（第二版）第2.3.3节

if nargin < 3
    accoutForClkErr = true;
end

[m, n] = size(RSat);
RUserRep = repmat(RUser', m, 1);
range = RSat - RUserRep;
rangeNorm = rss_cg(range, 2);
H = -range ./ repmat(rangeNorm, 1, n);
if accoutForClkErr
    H = [H ones(m, 1)];
end
A = inv(H'*H);
GDOP = sqrt(trace(A));
if n < 3
    A = horzinsert(A, 3, NaN);
    A = vertinsert(A, 3, NaN);
end
PDOP = sqrt(A(1, 1) + A(2, 2) + A(3, 3));
HDOP = sqrt(A(1, 1) + A(2, 2));
VDOP = sqrt(A(3, 3));
if accoutForClkErr
    TDOP = sqrt(A(4, 4));
else
    TDOP = NaN;
end
end